package jp.co.hcs.attendancemanagement.inputdailyattendance.logic;

import java.math.BigDecimal;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.Date;
import java.util.List;

import jp.co.hcs.attendancemanagement.AMConstants;
import jp.co.hcs.attendancemanagement.AMResourceKeyConstants;
import jp.co.hcs.attendancemanagement.AMResourceManager;
import jp.co.hcs.attendancemanagement.StrutsMessageConstants;
import jp.co.hcs.attendancemanagement.common.ApprovalRecordData;
import jp.co.hcs.attendancemanagement.common.ApprovalRecordRegister;
import jp.co.hcs.attendancemanagement.data.entity.EffortActual;
import jp.co.hcs.attendancemanagement.data.entity.Job;
import jp.co.hcs.attendancemanagement.data.entity.PositionMaster;
import jp.co.hcs.attendancemanagement.data.entity.RestTime;
import jp.co.hcs.attendancemanagement.data.entity.RestTimeActual;
import jp.co.hcs.attendancemanagement.data.entity.SubstituteHolidayActual;
import jp.co.hcs.attendancemanagement.data.entity.WorkingTimeActual;
import jp.co.hcs.attendancemanagement.exception.AMSQLException;
import jp.co.hcs.attendancemanagement.inputdailyattendance.actionform.InputDailyAttendanceForm;
import jp.co.hcs.attendancemanagement.inputdailyattendance.logic.dto.DailyWorkingActualResultDTO;
import jp.co.hcs.attendancemanagement.inputdailyattendance.logic.dto.EmployeeCompanyDTO;
import jp.co.hcs.attendancemanagement.inputdailyattendance.logic.dto.ProjectInfoDTO;
import jp.co.hcs.attendancemanagement.inputdailyattendance.logic.dto.RestTimeDTO;
import jp.co.hcs.attendancemanagement.inputdailyattendance.logic.dto.StampActualResultDTO;
import jp.co.hcs.attendancemanagement.util.DateUtil;
import jp.co.hcs.attendancemanagement.util.StringUtil;
import jp.co.hcs.attendancemanagement.util.TimeUtil;

import org.apache.struts.action.ActionErrors;
import org.apache.struts.action.ActionMessage;
import org.apache.struts.action.ActionMessages;

public class ConfirmDailyWorkingLogic extends InputDailyWorkingLogicBase {
    /**
     * Confirm daily working.
     * 
     * @param form the form
     * @return the action messages
   * @throws AMSQLException 
     * @throws SQLException the sQL exception
     */
    public ActionMessages confirmDailyWorking(InputDailyAttendanceForm form) throws AMSQLException {
      ActionMessages errors = new ActionMessages();

      // variables local
      // Register Take leave No, Daily Take leave No, Daily substitute leave adding No, Working time
      // checking exclusion flag
      String registerTakeLeaveNo;
      String dailyTakeLeaveNo;
      String dailySubstituteLeaveAddingNo;
      boolean workingTimeCheckingExclusionFlag = form.isWorkingTimeCheckExclusionFlag();
      String nonWorkingTime = TimeUtil.TIME_EMPTY;

      // [client] output message confirm

      try {
      daoFactory.startTransaction();
      
      // check input data before decision
      DailyWorkingActualResultDTO dailyWorking = form.getTimeDTO();

      String workingStartTime = dailyWorking.getWorkingStartTime();
      if (!StringUtil.isEmpty(workingStartTime)) {
        workingStartTime = StringUtil.fullWidthNumberToHalfWidthNumber(workingStartTime);
        dailyWorking.setWorkingStartTime(workingStartTime);
      }
      String workingStartDay = dailyWorking.getWorkingStartDay();
      if (!StringUtil.isEmpty(workingStartDay)) {
        workingStartDay = StringUtil.fullWidthNumberToHalfWidthNumber(workingStartDay);
        dailyWorking.setWorkingStartDay(workingStartDay);
      }
      String workingEndTime = dailyWorking.getWorkingEndTime();
      if (!StringUtil.isEmpty(workingEndTime)) {
        workingEndTime = StringUtil.fullWidthNumberToHalfWidthNumber(workingEndTime);
        dailyWorking.setWorkingEndTime(workingEndTime);
      }
      String workingEndDay = dailyWorking.getWorkingEndDay();
      if (!StringUtil.isEmpty(workingEndDay)) {
        workingEndDay = StringUtil.fullWidthNumberToHalfWidthNumber(workingEndDay);
        dailyWorking.setWorkingEndDay(workingEndDay);
      }

      roundWorkingTimeInfo(dailyWorking);

      // --check exiting of project code and work code
      List<ProjectInfoDTO> projectEffortList = form.getProjectInfoDTOList();

      // --check project list info
      for (ProjectInfoDTO projectDto : projectEffortList) {
        // check existing of project code and work code
        checkProjectCode(projectDto.getProjectCode(), projectDto.getSeri(), errors);
        checkWorkCode(projectDto.getWorkCode(), errors);
        
        // --check input working time
        if (TimeUtil.isTimeEmpty(projectDto.getWorkingTime())) {
          errors.add(ActionErrors.GLOBAL_MESSAGE, new ActionMessage(
              StrutsMessageConstants.ALARM_W1052_ERROR, AMResourceManager
                  .getMessage(AMResourceKeyConstants.FIELD_WORKINGTIME)));
          return errors;
        }
      }

      // --check input working time
      if (StringUtil.isEmpty(dailyWorking.getWorkingTime())) {
        errors.add(ActionErrors.GLOBAL_MESSAGE, new ActionMessage(
            StrutsMessageConstants.ALARM_W1052_ERROR, AMResourceManager
                .getMessage(AMResourceKeyConstants.FIELD_WORKINGTIME)));
        return errors;
      }

      // --get job division
      String jobType = dailyWorking.getJobDivision();

      // --check substitute leave day
      if (AMConstants.HOLIDAY_WORKING.equals(jobType)
          && !StringUtil.isEmpty(form.getSubstituteHoliday())) {
        // --phan doan gia tri flag nghi bu day du
        boolean fullRestFlag = false;
        EmployeeCompanyDTO employeeInfo = form.getInitDTO();
        PositionMaster position =
            getPositionMasterDAO().getPositionByIdWithFullRest(employeeInfo.getPositionCode());
        if (position != null) {
          fullRestFlag = true;
        }

        Job attendanceClassification = getJobDAO().selectJobByPrimaryKey(jobType);
        float minRestHoliday = attendanceClassification.getTransferHolidayTimeMin().floatValue();
        float maxRestHoliday = attendanceClassification.getTransferHolidayTimeMax().floatValue();
        String workingTime = dailyWorking.getWorkingTime();
        String substituteHolidayTime = dailyWorking.getSubstituteHolidayTime();
        // --check ngay nghi bu
        if (fullRestFlag) {
          if (!TimeUtil.isEqual(substituteHolidayTime, workingTime)) {
            errors.add(ActionErrors.GLOBAL_MESSAGE, new ActionMessage(
                StrutsMessageConstants.ALARM_W1053_ERROR, AMResourceManager
                    .getMessage(AMResourceKeyConstants.FIELD_SUBSTITUTEHOLIDAYTIME)));
            return errors;
          }
        } else {
          if (minRestHoliday > TimeUtil.convertTimeFromHHMM(workingTime)) {
            errors.add(ActionErrors.GLOBAL_MESSAGE, new ActionMessage(
                StrutsMessageConstants.ALARM_W1055_ERROR, AMResourceManager
                    .getMessage(AMResourceKeyConstants.FIELD_SUBSTITUTEHOLIDAY)));
            return errors;
          }

          float substituteHolidayTimeConverted = TimeUtil.convertTimeFromHHMM(substituteHolidayTime);
          if (!(minRestHoliday <= substituteHolidayTimeConverted && substituteHolidayTimeConverted <= maxRestHoliday)) {
            errors.add(ActionErrors.GLOBAL_MESSAGE, new ActionMessage(
                StrutsMessageConstants.ALARM_W1053_ERROR, AMResourceManager
                    .getMessage(AMResourceKeyConstants.FIELD_SUBSTITUTEHOLIDAYTIME)));
            return errors;
          }
        }
      }

      // --check total operating time
      if (!dailyWorking.getWorkingTime().equals(form.getTotalOperationTime())) {
        errors.add(ActionErrors.GLOBAL_MESSAGE, new ActionMessage(
            StrutsMessageConstants.ALARM_W1057_ERROR, AMResourceManager
                .getMessage(AMResourceKeyConstants.FIELD_OPERATIONTIME), AMResourceManager
                .getMessage(AMResourceKeyConstants.FIELD_WORKINGTIME)));
        return errors;
      }

      // --check total working time
      // totalWorkingTime = fixedWorkingTime + overWorkingTime + nightWorkTime + saturdayWorkTime +
      // saturdayNightWorkTime + substituteHolidayTime + holidayWorkTime +
      // holidayNightWorkTime + leaveTime;
      String overWorkingTime = dailyWorking.getOvertime();
      String nightWorkTime = dailyWorking.getNightWorkTime();
      String saturdayWorkTime = dailyWorking.getSatWorkingTime();
      String saturdayNightWorkTime = dailyWorking.getSatNightWorkTime();
      String substituteHolidayTime = dailyWorking.getSubstituteHolidayTime();
      String holidayWorkTime = dailyWorking.getHolidayWorkTime();
      String holidayNightWorkTime = dailyWorking.getHolidayNightWorkTime();
      String leaveTime = form.getLeaveTime();
      boolean wrongWorkingTimeDetail = false;
      if (workingTimeCheckingExclusionFlag
          && (!TimeUtil.isTimeEmpty(overWorkingTime) || !TimeUtil.isTimeEmpty(nightWorkTime)
              || !TimeUtil.isTimeEmpty(saturdayWorkTime)
              || !TimeUtil.isTimeEmpty(saturdayNightWorkTime)
              || !TimeUtil.isTimeEmpty(substituteHolidayTime)
              || !TimeUtil.isTimeEmpty(holidayWorkTime)
              || !TimeUtil.isTimeEmpty(holidayNightWorkTime))) {
        wrongWorkingTimeDetail = true;
      } else if (!workingTimeCheckingExclusionFlag) {
        List<String> workingTimeList = new ArrayList<String>();
        workingTimeList.add(dailyWorking.getFixedWorkingTime());
        workingTimeList.add(overWorkingTime);
        workingTimeList.add(nightWorkTime);
        workingTimeList.add(saturdayWorkTime);
        workingTimeList.add(saturdayNightWorkTime);
        workingTimeList.add(substituteHolidayTime);
        workingTimeList.add(holidayWorkTime);
        workingTimeList.add(holidayNightWorkTime);
        workingTimeList.add(leaveTime);
        String totalWorkingTime = TimeUtil.calculateTotalTime(workingTimeList);
        if (!totalWorkingTime.equals(dailyWorking.getWorkingTime())) {
          wrongWorkingTimeDetail = true;
        }
      }

      if (wrongWorkingTimeDetail) {
        errors.add(ActionErrors.GLOBAL_MESSAGE, new ActionMessage(
            StrutsMessageConstants.ALARM_W1057_ERROR, AMResourceManager
                .getMessage(AMResourceKeyConstants.FIELD_WORKINGTIME), AMResourceManager
                .getMessage(AMResourceKeyConstants.FIELD_WORKINGTIMEDETAIL)));
        return errors;
      }

      // --check over working time (20.2.3)
      if (TimeUtil.isGreaterThan(dailyWorking.getNightShiftWork(), dailyWorking.getFixedWorkingTime())) {
        errors.add(ActionErrors.GLOBAL_MESSAGE, new ActionMessage(
            StrutsMessageConstants.ALARM_W1053_ERROR, AMResourceManager
                .getMessage(AMResourceKeyConstants.FIELD_OVERWORKINGTIME)));
        return errors;
      }

      // --check effort duplicate
      ProjectInfoDTO projectObj1;
      ProjectInfoDTO projectObj2;
      for (int i = 0; i < projectEffortList.size() - 1; i++) {
        projectObj1 = projectEffortList.get(i);
        for (int j = i + 1; j < projectEffortList.size(); j++) {
          projectObj2 = projectEffortList.get(j);
          if (projectObj1.equals(projectObj2)) {
            errors.add(ActionErrors.GLOBAL_MESSAGE, new ActionMessage(
                StrutsMessageConstants.ALARM_W1096_ERROR, AMResourceManager
                    .getMessage(AMResourceKeyConstants.MSG_PROJECTEFFORTDUPLICATE)));
            return errors;
          }
        }
      }

      // delete data take leave
      dailyTakeLeaveNo = dailyWorking.getTakingVacationNo();
      if (!StringUtil.isEmpty(dailyTakeLeaveNo)) {
        try {
          getRestTimeActualDAO().deleteRestTimeActualByPrimaryKey(dailyTakeLeaveNo);
        } catch (SQLException e) {
          // rollback end 21.2
          errors.add(ActionErrors.GLOBAL_MESSAGE, new ActionMessage(
              StrutsMessageConstants.ALARM_W1061_ERROR, AMResourceManager
                  .getMessage(AMResourceKeyConstants.ACTION_UPDATEPROCESS)));
          return errors;
        }
      }

      // delete data take substitute leave
      dailySubstituteLeaveAddingNo = dailyWorking.getAddedSubstituteHolidayNo();

      if (!StringUtil.isEmpty(dailySubstituteLeaveAddingNo)) {
        // --check da su dung het data substitute leave chua?
        SubstituteHolidayActual addedSubstituteHoliday =
            getSubstituteHolidayActualDAO().selectSubstituteHolidayActualByPrimaryKey(
                dailySubstituteLeaveAddingNo);
        if (addedSubstituteHoliday == null) {
          // rollback end 21.2
          errors.add(ActionErrors.GLOBAL_MESSAGE, new ActionMessage(
              StrutsMessageConstants.ALARM_W1061_ERROR, AMResourceManager
                  .getMessage(AMResourceKeyConstants.ACTION_UPDATEPROCESS)));
          return errors;
        } else if (addedSubstituteHoliday.getSubstituteHolidayDeleteDay() != null) {
          // rollback end 21.2
          errors.add(ActionErrors.GLOBAL_MESSAGE, new ActionMessage(
              StrutsMessageConstants.ALARM_W1063_ERROR, AMResourceManager
                  .getMessage(AMResourceKeyConstants.FIELD_SUBSTITUTELEAVETAKINGDAY)));
          return errors;
        }

        // --delete data substitute leave
        try {
          getSubstituteHolidayActualDAO().deleteSubstituteHolidayActualByPrimaryKey(
              dailySubstituteLeaveAddingNo);
          dailyWorking.setAddedSubstituteHolidayNo("");
        } catch (SQLException e) {
          // rollback end 21.2
          errors.add(ActionErrors.GLOBAL_MESSAGE, new ActionMessage(
              StrutsMessageConstants.ALARM_W1061_ERROR, AMResourceManager
                  .getMessage(AMResourceKeyConstants.ACTION_UPDATEPROCESS)));
          return errors;
        }
      }

      // 21.5 dang ky data su dung substitute leave
      String substituteLeaveNo = "";
      if (AMConstants.SUBSTITUTE_LEAVE.equals(jobType)) {
        // --check substitute leave remaining
        substituteLeaveNo =
            getSubstituteHolidayActualDAO().getOldestSubstituteLeaveNoByUserId(form.getUserId());
        if (StringUtil.isEmpty(substituteLeaveNo)) {
          errors.add(ActionErrors.GLOBAL_MESSAGE, new ActionMessage(
              StrutsMessageConstants.ALARM_W1051_ERROR, AMResourceManager
                  .getMessage(AMResourceKeyConstants.FIELD_SUBSTITUTEHOLIDAYREMAINING)));
          return errors;
        }

        // --update data substitute leave
        SubstituteHolidayActual sha = new SubstituteHolidayActual();
        sha.setSubstituteHolidayId(substituteLeaveNo);
        sha.setSubstituteHolidayDeleteDay(DateUtil.parseDate(form.getMonth() + "/" + form.getDay(),
            form.getYear()));
        int result =
            getSubstituteHolidayActualDAO().updateSubstituteHolidayActualByPrimaryKeySelective(sha);
        if (result == 0) {
          // rollback 21.2
          errors.add(ActionErrors.GLOBAL_MESSAGE, new ActionMessage(
              StrutsMessageConstants.ALARM_W1061_ERROR, AMResourceManager
                  .getMessage(AMResourceKeyConstants.ACTION_UPDATEPROCESS)));
          return errors;
        }
      }

      // dang ky data thuc te su dung ngay nghi
      Job attendanceClassification = getJobDAO().selectJobByPrimaryKey(jobType);
      if (attendanceClassification.getIsRest() || attendanceClassification.getIsMorningRest()
          || attendanceClassification.getIsAfternoonRest()) {
        // --get sequence dung cho Take leave No
        String empFullId = StringUtil.fillZeroBefore(form.getUserId(), 10);
        String screenDate = form.getYear() + form.getMonth() + form.getDay();
        List<String> seqNoList =
            getRestTimeActualDAO().getRestTimeActualSeqNum(empFullId, screenDate);
        if (seqNoList != null && seqNoList.size() > 0) {
          Collections.sort(seqNoList, new Comparator<String>() {
            public int compare(String o1, String o2) {
              return o2.compareTo(o1);
            }
          });
          String takeLeaveNo = seqNoList.get(0);
          int seriNum = Integer.parseInt(takeLeaveNo.substring(18));
          registerTakeLeaveNo = empFullId + screenDate + StringUtil.parseZeroString(++seriNum);
        } else {
          registerTakeLeaveNo = empFullId + screenDate + "01";
        }

        // --dang ky Take leave result
        RestTimeActual rtaObj = new RestTimeActual();
        rtaObj.setRestTakingId(registerTakeLeaveNo);
        rtaObj.setRestType(jobType);
        rtaObj.setChangeHolidayAddingNo(AMConstants.SUBSTITUTE_LEAVE.equals(jobType)
            ? substituteLeaveNo : "");
        rtaObj.setRestTakingStartDate(DateUtil.parseDate(form.getMonth() + "/" + form.getDay(), form
            .getYear()));
        rtaObj.setRestTakingDays(new BigDecimal(1));
        rtaObj.setRestTakingTime(DateUtil.parseDateFromHHmm(dailyWorking.getPaidHoliday()));
        rtaObj.setIsHalfRest(attendanceClassification.getIsMorningRest()
            || attendanceClassification.getIsAfternoonRest());
        rtaObj.setEmployeeId(form.getUserId());
        rtaObj.setRegisterId(form.getUserId());
        rtaObj.setRegisterDate(new Date());
        try {
          getRestTimeActualDAO().insertRestTimeActualSelective(rtaObj);
          dailyTakeLeaveNo = rtaObj.getRestTakingId();
          dailyWorking.setTakingVacationNo(dailyTakeLeaveNo);
        } catch (SQLException e) {
          // rollback end 21.2
          errors.add(ActionErrors.GLOBAL_MESSAGE, new ActionMessage(
              StrutsMessageConstants.ALARM_W1061_ERROR, AMResourceManager
                  .getMessage(AMResourceKeyConstants.ACTION_UPDATEPROCESS)));
          return errors;
        }
      }

      // --dang ky substitute leave adding
      String substituteHolidayPlannedDay = form.getSubstituteHoliday();
      if (AMConstants.HOLIDAY_WORKING.equals(jobType)
          && !StringUtil.isEmpty(substituteHolidayPlannedDay)) {
        SubstituteHolidayActual sha = new SubstituteHolidayActual();
        String substituteHolidayId =
            StringUtil.fillZeroBefore(form.getUserId(), 10) + form.getYear() + form.getMonth()
                + form.getDay();
        sha.setSubstituteHolidayId(substituteHolidayId);
        sha.setEmployeeId(form.getUserId());
        sha.setAddedSubstituteHolidayDay(DateUtil.parseDate(form.getMonth() + "/" + form.getDay(),
            form.getYear()));
        sha.setSubstituteHolidayPlannedDay(DateUtil.parseDate(substituteHolidayPlannedDay, form
            .getYear()));
        sha.setRegisterId(form.getUserId());
        sha.setRegisterDate(new Date());
        getSubstituteHolidayActualDAO().insertSubstituteHolidayActualSelective(sha);
        dailyWorking.setAddedSubstituteHolidayNo(substituteHolidayId);
      }

      // edit after confirm
      // --edit status
      dailyWorking.setDailyWorkingApprovalStatus(StringUtil.CONFIRMED_VALUE);
      // --edit decision info
      String confirmId = form.getUserId();
      Date confirmDate = new Date();
      
      StampActualResultDTO stampActual = form.getStampActualResultDTO();
      String stampStartDay = stampActual.getComingWorkDay();
      String stampStartTime = stampActual.getComingWorkTime();
      String stampEndDay = stampActual.getLeavingWorkDay();
      String stampEndTime = stampActual.getLeavingWorkTime();
      
      // --edit thoi gian ko lao dong
      if (!StringUtil.isEmpty(stampStartDay)
              && !StringUtil.isEmpty(stampEndDay)
              && !StringUtil.isEmpty(workingStartDay)
              && !StringUtil.isEmpty(workingEndDay)) {
          if (stampStartDay.equals(workingStartDay)
                  && (!stampActual.getChokkoFlag() || !dailyWorking
                          .getCommutingDelayFlag())) {
              // nonWorkingTime = stamp start time - working start time
              nonWorkingTime = TimeUtil.sub(stampStartTime,
                      workingStartTime);
          }
          if (DateUtil.isBefore(stampStartDay, workingStartDay)) {
              // nonWorkingTime = (24:00 - Stamp start time) + Working
              // start time
              nonWorkingTime = TimeUtil.sum(
                      TimeUtil.sub("24:00", stampStartTime),
                      workingStartTime);
          }
          if (stampEndDay.equals(workingEndDay)
                  && !stampActual.getChokkiFlag()) {
              // nonWorkingTime = nonWorkingTime + (stampEndTime -
              // workingEndTime);
              nonWorkingTime = TimeUtil.sum(nonWorkingTime,
                      TimeUtil.sub(stampEndTime, workingEndTime));
          }
          if (DateUtil.isBefore(workingEndDay, stampEndDay)) {
              // nonWorkingTime = nonWorkingTime + (stampEndTime +
              // ("24:00" - workingEndTime));
              nonWorkingTime = TimeUtil.sum(
                      nonWorkingTime,
                      TimeUtil.sum(stampEndTime,
                              TimeUtil.sub("24:00", workingEndTime)));
          }
      }
      
      String dailyOvertimeTotal = calculateDailyOvertimeTotal(dailyWorking);
      String specialOvertime = calculateSpecialOvertime(dailyWorking);

      // dang ky Daily working result
      // update data lam viec/nghi theo ngay
      String employeeId = form.getUserId();
      String yearMonth = form.getYear() + form.getMonth();
      String day = form.getDay();
      WorkingTimeActual workingTimeActual =
          getWorkingTimeActualDAO().selectWorkingTimeActualByPrimaryKey(employeeId, day, yearMonth);
      if (workingTimeActual == null) {
        workingTimeActual = new WorkingTimeActual();
        workingTimeActual.setEmployeeId(employeeId);
        workingTimeActual.setActualWorkingYearMonth(yearMonth);
        workingTimeActual.setActualWorkingDay(day);
        workingTimeActual.setRegisterId(employeeId);
        workingTimeActual.setRegisterDate(new Date());
        workingTimeActual.setRegisterTime(new Date());
        copyPropertiesDailyWorking(dailyWorking, workingTimeActual, form.getYear());
        workingTimeActual.setNonWorkingTime(DateUtil.parseDateFromHHmm(nonWorkingTime));
        workingTimeActual.setTotalOvertimePerDay(DateUtil.parseDateFromHHmm(dailyOvertimeTotal));
        workingTimeActual.setSpecialOvertimeTime(DateUtil.parseDateFromHHmm(specialOvertime));
        getWorkingTimeActualDAO().insertWorkingTimeActualSelective(workingTimeActual);
      } else {
        workingTimeActual.setEmployeeId(employeeId);
        workingTimeActual.setActualWorkingYearMonth(yearMonth);
        workingTimeActual.setActualWorkingDay(day);
        workingTimeActual.setChangePersonId(employeeId);
        workingTimeActual.setChangeDate(new Date());
        workingTimeActual.setChangeTime(new Date());
        copyPropertiesDailyWorking(dailyWorking, workingTimeActual, form.getYear());
        workingTimeActual.setNonWorkingTime(DateUtil.parseDateFromHHmm(nonWorkingTime));
        workingTimeActual.setTotalOvertimePerDay(DateUtil.parseDateFromHHmm(dailyOvertimeTotal));
        workingTimeActual.setSpecialOvertimeTime(DateUtil.parseDateFromHHmm(specialOvertime));
        getWorkingTimeActualDAO().updateWorkingTimeActualByPrimaryKey(workingTimeActual);
      }

      // update data thoi gian nghi giai lao
      // --delete data daily working_rest time
      getRestTimeDAO().deleteRestTimeInDay(employeeId, day, yearMonth);

      // --dang ky data daily working_rest time
      String year = form.getYear();
      List<RestTimeDTO> restTimeList = form.getRestTimeInfoDTOList();
      if (restTimeList != null) {
        RestTime restObj;
        for (RestTimeDTO restDto : restTimeList) {
          if (!StringUtil.isEmpty(restDto.getRestStartTime())
              && !StringUtil.isEmpty(restDto.getRestEndTime())) {
            restObj = new RestTime();
            restObj.setEmployeeId(employeeId);
            restObj.setActualWorkingDay(day);
            restObj.setActualWorkingYearMonth(yearMonth);
            restObj.setTakingRestNum((short) restDto.getTakingRestNum());
            restObj.setRestTime(DateUtil.parseDateFromHHmm(restDto.getRestTime()));
            restObj.setRestStartTime(DateUtil.parseDateFromHHmm(restDto.getRestStartTime()));
            restObj.setRestEndTime(DateUtil.parseDateFromHHmm(restDto.getRestEndTime()));
            restObj.setComment(restDto.getComment());
            getRestTimeDAO().insertRestTimeSelective(restObj);
          }
        }
      }

      // update data daily effort actual
      // --delete data daily effort
      getEffortActualDAO().deleteEffortActualInDay(employeeId, day, yearMonth);

      // --dang ky data daily effort actual
      EffortActual effortObj;
      Date now = new Date();
      int seqNo = 0;
      for (ProjectInfoDTO prjInfoDto : projectEffortList) {
        if (!StringUtil.isEmpty(prjInfoDto.getProjectCode())
            && !StringUtil.isEmpty(prjInfoDto.getSeri())
            && !StringUtil.isEmpty(prjInfoDto.getWorkCode())
            && !StringUtil.isEmpty(prjInfoDto.getWorkingTime())) {
          effortObj = new EffortActual();
          effortObj.setEmployeeId(employeeId);
          effortObj.setActualEffortYearMonth(yearMonth);
          effortObj.setActualEffortDay(day);
          effortObj.setSeqNo((short) ++seqNo);
          effortObj.setRegisterId(employeeId);
          effortObj.setRegisterDate(now);
          effortObj.setRegisterTime(now);
          effortObj.setProjectId(prjInfoDto.getProjectNumber());
          effortObj.setProjectCode(prjInfoDto.getProjectCode());
          effortObj.setWorkingId(prjInfoDto.getWorkCode());
          effortObj.setWorkingTime(DateUtil.parseDateFromHHmm(StringUtil
              .fullWidthNumberToHalfWidthNumber(prjInfoDto.getWorkingTime())));
          effortObj.setComment(prjInfoDto.getComment());
          getEffortActualDAO().insertEffortActualSelective(effortObj);
        }
      }

      ApprovalRecordRegister approvalRegister = new ApprovalRecordRegister();
      ApprovalRecordData approvalData = new ApprovalRecordData();

      // register data daily working approval
      approvalData.setEmployeeId(employeeId);
      approvalData.setApprovalTypeId(AMConstants.APPROVAL_TYPE_DAILY);
      approvalData.setTargetYearMonth(yearMonth);
      approvalData.setTargetDay(day);
      approvalData.setTimingRegistCode(0);
      approvalData.setDayRegistCode(1);
      approvalData.setEffortRegistCode(1);
      approvalData.setApplicationNo("");
      approvalData.setProgramId(AMConstants.PGM_5031_SCREEN_ID);
      int resultCode = approvalRegister.registerApproval(approvalData);
      if (resultCode == AMConstants.ERROR_FINISH) {
        // rollback
        errors.add(ActionErrors.GLOBAL_MESSAGE, new ActionMessage(
            StrutsMessageConstants.ALARM_W1061_ERROR, AMResourceManager
                .getMessage(AMResourceKeyConstants.ACTION_UPDATEPROCESS)));
        return errors;
      }

      // register data Monthly working approval
      approvalData.setEmployeeId(employeeId);
      approvalData.setApprovalTypeId(AMConstants.APPROVAL_TYPE_MONTHLY);
      approvalData.setTargetYearMonth(yearMonth);
      approvalData.setTargetDay("");
      approvalData.setTimingRegistCode(0);
      approvalData.setDayRegistCode(0);
      approvalData.setEffortRegistCode(0);
      approvalData.setApplicationNo("");
      approvalData.setProgramId(AMConstants.PGM_5031_SCREEN_ID);
      resultCode = approvalRegister.registerApproval(approvalData);
      if (resultCode == AMConstants.ERROR_FINISH) {
        // rollback
        errors.add(ActionErrors.GLOBAL_MESSAGE, new ActionMessage(
            StrutsMessageConstants.ALARM_W1061_ERROR, AMResourceManager
                .getMessage(AMResourceKeyConstants.ACTION_UPDATEPROCESS)));
        return errors;
      }

      // commit data
      daoFactory.commitTransaction();
      
      }
      catch (SQLException e) {
        throw new AMSQLException(e.getMessage());
      }
      catch (Exception e) {
          throw new AMSQLException(e.getMessage());
        }
      finally {
        try {
          daoFactory.endTransaction();
        } catch (SQLException e) {
          throw new AMSQLException(e.getMessage());
        }
      }

      // output message successful
      return errors;
    }
    
}
